package qc.module.platform.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.ResourceStatusFlagEnum;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.module.platform.dto.db.DBDto;
import qc.module.platform.entity.QcDb;
import qc.module.platform.entity.QcDbTable;
import qc.module.platform.entity.QcDbTableColumn;
import qc.module.platform.entity.QcDbTableSql;
import qc.module.platform.mapper.DBMapper;
import qc.module.platform.repository.QcDbRepository;
import qc.module.platform.repository.QcDbTableColumnRepository;
import qc.module.platform.repository.QcDbTableRepository;
import qc.module.platform.repository.QcDbTableSqlRepository;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * DbService
 *
 * @author QuCheng Tech
 * @since 2024/2/1
 */
@Service
public class DbService {
    private QcDbRepository repository;
    
    @Autowired
    private QcDbTableRepository dbTableRepository;
    
    @Autowired
    private QcDbTableSqlRepository dbTableSqlRepository;
    
    @Autowired
    private QcDbTableColumnRepository dbTableColumnRepository;

    @Autowired
    public void setRepository(QcDbRepository repository) {
        this.repository = repository;
    }

    /**
     * 获取所有
     * @return 返回数据库信息集合
     * @author QuCheng
     * @since 2024/3/12
     */
    public List<DBDto> getAll(){
        LambdaQueryWrapper<QcDb> wrapper = new LambdaQueryWrapper<>();
        List<QcDb> ens = repository.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(ens)) return DBMapper.MAPPER.toDtoList(ens);
        return null;
    }

    /***
     * 获取指定表编码的表信息
     *
     * @param dbCode 表编码
     * @return qc.module.platform.dto.dbTable.DBTableDto
     * @author QuCheng Tech
     * @since 2024/2/1
     */
    public DBDto get(String dbCode) throws QCPromptException {
        if (StringUtils.isBlank(dbCode))
            throw new QCPromptException("查询数据库信息时指定的数据库代码不能为空");

        LambdaQueryWrapper<QcDb> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(QcDb::getCode, dbCode);

        QcDb en = repository.selectOne(wrapper);
        if (en != null)
            return DBMapper.MAPPER.toDto(en);

        return null;
    }

    /**
     * 新增
     * @param dbDto
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng
     * @since 2024/3/12
     */
    public String add(DBDto dbDto){
        // 1.新增对象判空
        if (Objects.isNull(dbDto)) return QCUnifyReturnValue.Warn("对象不能为空");
        if (StringUtils.isBlank(dbDto.getCode())) return QCUnifyReturnValue.Warn("数据库编码不能为空");
        if (StringUtils.isBlank(dbDto.getName())) return QCUnifyReturnValue.Warn("数据库名称不能为空");
        if (StringUtils.isBlank(dbDto.getCon())) return QCUnifyReturnValue.Warn("数据库的连接信息不能为空");
        
        // 2.判断数据库编码是否已经存在
        if(isExist(dbDto.getCode()))
            return QCUnifyReturnValue.Warn("数据库编码已存在");
        
        // 3.dto转换为entity
        QcDb entity = DBMapper.MAPPER.toEntity(dbDto);
        
        // 4.保存数据
        if (repository.insert(entity) < 0x1)
            return QCUnifyReturnValue.Warn("新增数据失败");
        return QCUnifyReturnValue.Success();
    }

    /**
     * 修改
     * @param dbDto
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng
     * @since 2024/3/12
     */
    public String update(DBDto dbDto) {
        // 1.修改对象判空
        if (Objects.isNull(dbDto)) return QCUnifyReturnValue.Warn("对象不能为空");
        if (StringUtils.isBlank(dbDto.getCode())) return QCUnifyReturnValue.Warn("数据库编码不能为空");
        if (StringUtils.isBlank(dbDto.getName())) return QCUnifyReturnValue.Warn("数据库名称不能为空");
        if (StringUtils.isBlank(dbDto.getCon())) return QCUnifyReturnValue.Warn("数据库的连接信息不能为空");
        
        // 2.判断修改的对象是否存在，不存在则提示
        if(!isExist(dbDto.getCode()))
            return QCUnifyReturnValue.Warn("修改的数据库信息不存在");

        // 3.dto转换为entity
        QcDb en = DBMapper.MAPPER.toEntity(dbDto);
        
        // 4.修改数据
        repository.updateById(en);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 删除指定数据库编码信息，同时删除数据库表信息、数据库表sql信息和数据库表column信息。
     * @param dbCode 数据库编码
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng
     * @since 2024/3/12
     */
    public String delete(String dbCode) throws QCPromptException {
        // 1.条件判空
        if (StringUtils.isBlank(dbCode))
            throw new QCPromptException("查询数据库信息时指定的数据库代码不能为空");
        
        // 2.根据数据库编码查询数据库表信息集合
        LambdaQueryWrapper<QcDbTable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QcDbTable::getDb,dbCode);
        List<QcDbTable> tables = dbTableRepository.selectList(wrapper);
        
        if (CollectionUtils.isNotEmpty(tables)){
            // 2.1 获取数据库表编码集合
            List<String> tableCodes = tables.stream().map(QcDbTable::getCode).collect(Collectors.toList());
            
            if (CollectionUtils.isNotEmpty(tableCodes)){
                tableCodes.stream().forEach(tbCode -> {
                    // 2.2 根据数据库表编码删除数据库表sql信息（物理删除）
                    LambdaQueryWrapper<QcDbTableSql> sqlWrapper = new LambdaQueryWrapper<>();
                    sqlWrapper.eq(QcDbTableSql::getTbcode,tbCode);
                    dbTableSqlRepository.delete(sqlWrapper);
                    
                    // 2.3 根据数据库表编码删除数据库表column信息（物理删除）
                    LambdaQueryWrapper<QcDbTableColumn> columnWrapper = new LambdaQueryWrapper<>();
                    columnWrapper.eq(QcDbTableColumn::getTbcode,tbCode);
                    dbTableColumnRepository.delete(columnWrapper);
                });
            }
            
            // 2.4 删除数据库表信息（物理删除）
            dbTableRepository.delete(wrapper);
        }
        
        // 5.删除指定数据库编码数据
        repository.deleteById(dbCode);
        return QCUnifyReturnValue.Success();
    }

    /**
     * 判断数据库编码对象是否存在
     * @param dbCode 数据库编码
     * @return 返回true表示存在，false表示不存在
     * @author QuCheng Tech
     * @since 2024/3/13
     */
    public boolean isExist(String dbCode){
        if (Objects.nonNull(repository.selectById(dbCode)))
            return true;
        return false;
    }
}
